package com.pulse.base.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.pulse.base.domain.CircuitMeasure;
import com.pulse.base.domain.CircuitMeasureEvent;
import com.pulse.base.domain.CircuitMeasureRefer;
import com.pulse.base.domain.FilePath;
import com.pulse.base.mapper.CircuitMeasureMapper;
import com.pulse.base.service.ICircuitMeasureEventService;
import com.pulse.base.service.ICircuitMeasureReferService;
import com.pulse.base.service.ICircuitMeasureService;
import com.pulse.base.service.IFilePathService;
import com.pulse.common.annotation.DataScope;
import com.pulse.common.config.PulseConfig;
import com.pulse.common.constant.Constants;
import com.pulse.common.exception.ServiceException;
import com.pulse.common.utils.SecurityUtils;
import com.pulse.common.utils.StringUtils;
import com.pulse.common.utils.file.FileUploadUtils;
import com.pulse.common.utils.sor.FxdParams;
import com.pulse.common.utils.sor.Sor;
import com.pulse.common.utils.sor.domain.EventVo;
import com.pulse.common.utils.sor.domain.FxdParamsVo;
import com.pulse.common.utils.sor.domain.KeyEventsVo;
import com.pulse.common.utils.sor.domain.SorInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * 光路监测Service业务层处理
 *
 * @author 陆帅
 * @date 2024-07-17
 */
@Service
public class CircuitMeasureServiceImpl implements ICircuitMeasureService {

    @Autowired
    private CircuitMeasureMapper circuitMeasureMapper;
    @Autowired
    private ICircuitMeasureReferService circuitMeasureReferService;
    @Autowired
    private IFilePathService filePathService;
    @Autowired
    private ICircuitMeasureEventService circuitMeasureEventService;

    /**
     * 新增
     *
     * @param circuitMeasure
     * @return
     */
    @Override
    public int insertCircuitMeasure(CircuitMeasure circuitMeasure) {
        return circuitMeasureMapper.insertCircuitMeasure(circuitMeasure);
    }

    /**
     * 更新
     *
     * @param circuitMeasure
     * @return
     */
    @Override
    public int updateCircuitMeasure(CircuitMeasure circuitMeasure) {
        return circuitMeasureMapper.updateCircuitMeasure(circuitMeasure);
    }

    /**
     * 设置参考曲线
     *
     * @param measureId
     * @return
     */
    @Override
    @Transactional
    public int setDefaultMeasure(Long measureId) {
        CircuitMeasure circuitMeasure = circuitMeasureMapper.selectCircuitMeasureByMeasureId(measureId);
        if(circuitMeasure == null) return -1;

        // 判断是否已经存在参考曲线，如果存在则将之前的参考曲线修改为非参考曲线
        CircuitMeasureRefer circuitMeasureRefer = circuitMeasureReferService.selectCircuitMeasureReferByDeviceNoAndChannel(circuitMeasure.getDeviceNo(),circuitMeasure.getChannel());
        if(circuitMeasureRefer != null){
            CircuitMeasure cm = circuitMeasureMapper.selectCircuitMeasureByMeasureId(circuitMeasureRefer.getMeasureId());
            if (cm != null) {
                cm.setDefaultMeasure(0);
                circuitMeasureMapper.updateCircuitMeasure(cm);
            }
        }else{
            circuitMeasureRefer = new CircuitMeasureRefer();
        }

        circuitMeasureRefer.setMeasureId(measureId);
        circuitMeasureRefer.setDeviceNo(circuitMeasure.getDeviceNo());
        circuitMeasureRefer.setChannel(circuitMeasure.getChannel());
        circuitMeasureRefer.setStatus(0);

        try{
            circuitMeasureRefer.setFullLength(Double.parseDouble(circuitMeasure.getWholeLen()));
            circuitMeasureRefer.setFullAtten(Double.parseDouble(circuitMeasure.getWholeAtten()));
        }
        catch (Exception e){
            String msg = "设置失败，数据格式错误";
            throw new ServiceException(msg);
        }

        if(circuitMeasureRefer.getReferId() == null){
            circuitMeasureReferService.insertCircuitMeasureRefer(circuitMeasureRefer);
        }
        else{
            circuitMeasureReferService.updateCircuitMeasureRefer(circuitMeasureRefer);
        }

        return circuitMeasureMapper.setDefaultMeasure(measureId);
    }

    /**
     * 查询光路监测列表
     *
     * @param circuitMeasure
     * @return
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<CircuitMeasure> selectCircuitMeasureList(CircuitMeasure circuitMeasure) {
        return circuitMeasureMapper.selectCircuitMeasureList(circuitMeasure);
    }

    /**
     * 删除光路监测曲线
     *
     * @param measureIds
     * @return
     */
    @Override
    public int deleteCircuitMeasureByMeasureIds(Long[] measureIds) {
        for (Long measureId : measureIds) {
            circuitMeasureEventService.deleteByMeasureId(measureId);
            circuitMeasureReferService.deleteByMeasureId(measureId);
            CircuitMeasure circuitMeasure = circuitMeasureMapper.selectCircuitMeasureByMeasureId(measureId);
            Long fileId = circuitMeasure.getFileId();
            if (fileId == null) {
                continue;
            }
            FilePath filePath = filePathService.selectFilePathByFileId(fileId);

            int dirLastIndex = Constants.RESOURCE_PREFIX.length() + 1;
            String currentDir = StringUtils.substring(filePath.getFilePath(), dirLastIndex);
            String absPath = PulseConfig.getProfile() + "/" + currentDir;
            Path path = Paths.get(absPath);
            try{
                boolean deleted = Files.deleteIfExists(path);
                if(deleted) {
                    System.out.println("文件删除成功");
                    filePathService.deleteFilePathByFileId(fileId);
                } else {
                    System.out.println("文件不存在");
                }
            }
            catch (Exception e){
                System.out.println("删除过程中出错: " + e.getMessage());
            }
        }
        return circuitMeasureMapper.deleteCircuitMeasureByMeasureIds(measureIds);
    }

    /**
     * 查看曲线
     *
     * @param measureIds
     * @return
     */
    @Override
    public List<Map<String, Object>> viewCurve(Long[] measureIds) {
        List<Map<String, Object>> res = new ArrayList<>();
        for (Long measureId : measureIds) {
            CircuitMeasure circuitMeasure = circuitMeasureMapper.selectCircuitMeasureByMeasureId(measureId);
            if (circuitMeasure == null) {
                continue;
            }
            FilePath filePath = filePathService.selectFilePathByFileId(circuitMeasure.getFileId());
            if (filePath == null) {
                continue;
            }

            int dirLastIndex = Constants.RESOURCE_PREFIX.length() + 1;
            String currentDir = StringUtils.substring(filePath.getFilePath(), dirLastIndex);
            String absPath = PulseConfig.getProfile() + "/" + currentDir;

            Path fPath = Paths.get(absPath);

            List<String> tracedata = null;
            Double PKP = 0d;
            try {
                Map<String, Object> parse = Sor.parse(fPath);
                if(parse.get("status").equals("ok")){
                    SorInfo sorInfo = (SorInfo) parse.get("sorInfo");
                    tracedata = sorInfo.getDataPts().getTracedata();
                    PKP = sorInfo.getFxdParams().getResolution();
                }
            } catch (Exception e) {
                String msg = "曲线[%d]获取失败";
                String msg1 = String.format(msg, measureId);
                throw new ServiceException(msg1);
            }


            // 查询事件
            List<CircuitMeasureEvent> circuitMeasureEvents = circuitMeasureEventService.selectCircuitMeasureEventByMeasureId(measureId);

            Map<String, Object> measure = new HashMap<>();
            measure.put("measureId", measureId);
            measure.put("deviceNo", circuitMeasure.getDeviceNo());
            measure.put("channel", circuitMeasure.getChannel());
            measure.put("createTime", circuitMeasure.getCreateTime());
            measure.put("events", circuitMeasureEvents);
            measure.put("tracedata",tracedata);
            measure.put("PKP",PKP);
            res.add(measure);
        }
        return res;
    }

    /**
     * 查询光路监测曲线
     *
     * @param measureId
     * @return
     */
    @Override
    public CircuitMeasure selectCircuitMeasureByMeasureId(Long measureId) {
        return circuitMeasureMapper.selectCircuitMeasureByMeasureId(measureId);
    }

    /**
     * 根据曲线id查询参考曲线
     *
     * @param measureId
     * @return
     */
    @Override
    public CircuitMeasure getDefaultMeasure(Long measureId) {
        CircuitMeasure cm = circuitMeasureMapper.selectCircuitMeasureByMeasureId(measureId);
        if (cm == null) {
            return null;
        }
        CircuitMeasureRefer circuitMeasureRefer = circuitMeasureReferService.selectCircuitMeasureReferByDeviceNoAndChannel(cm.getDeviceNo(),cm.getChannel());
        if (circuitMeasureRefer == null) {
            return null;
        }
        CircuitMeasure circuitMeasure = circuitMeasureMapper.selectCircuitMeasureByMeasureId(circuitMeasureRefer.getMeasureId());
        List<CircuitMeasureEvent> circuitMeasureEvents = circuitMeasureEventService.selectCircuitMeasureEventByMeasureId(circuitMeasure.getMeasureId());
        circuitMeasure.setEvents(circuitMeasureEvents);
        return circuitMeasure;
    }

    /**
     * 根据设备编号删除
     *
     * @param deviceNo
     * @return
     */
    @Override
    @Transactional
    public int deleteCircuitMeasureByDeviceNo(String deviceNo) {
        // 删除refer
        circuitMeasureReferService.deleteByDeviceNo(deviceNo);
        // 删除文件
        List<CircuitMeasure> circuitMeasureList = circuitMeasureMapper.selectCircuitMeasureByDeviceNo(deviceNo);
        List<Long> measureIds = new ArrayList<>();
        for (CircuitMeasure circuitMeasure : circuitMeasureList) {
            measureIds.add(circuitMeasure.getMeasureId());

            Long fileId = circuitMeasure.getFileId();
            if (fileId == null) {
                continue;
            }
            FilePath filePath = filePathService.selectFilePathByFileId(fileId);

            int dirLastIndex = Constants.RESOURCE_PREFIX.length() + 1;
            String currentDir = StringUtils.substring(filePath.getFilePath(), dirLastIndex);
            String absPath = PulseConfig.getProfile() + "/" + currentDir;
            Path path = Paths.get(absPath);
            try{
                boolean deleted = Files.deleteIfExists(path);
                if(deleted) {
                    System.out.println("文件删除成功");
                    filePathService.deleteFilePathByFileId(fileId);
                } else {
                    System.out.println("文件不存在");
                }
            }
            catch (Exception e){
                System.out.println("删除过程中出错: " + e.getMessage());
            }

        }
        // 删除event
        if(measureIds.size() >0){
            circuitMeasureEventService.deleteByMeasureIds(measureIds);
        }
        return circuitMeasureMapper.deleteCircuitMeasureByDeviceNo(deviceNo);
    }

    /**
     * 导出sor文件
     *
     * @param response
     * @param circuitMeasure
     */
    @Override
    public void exportSor(HttpServletResponse response, CircuitMeasure circuitMeasure) throws IOException {
        CircuitMeasure cm = circuitMeasureMapper.selectCircuitMeasureByMeasureId(circuitMeasure.getMeasureId());
        if(cm==null){
            throw new ServiceException("导出失败");
        }

        Long fileId = cm.getFileId();
        if(fileId == null){
            throw new ServiceException("导出失败");
        }

        FilePath filePath = filePathService.selectFilePathByFileId(fileId);
        // 将保存的路径转换成绝对路径
        int dirLastIndex = Constants.RESOURCE_PREFIX.length() + 1;
        String currentDir = StringUtils.substring(filePath.getFilePath(), dirLastIndex);
        String absPath = PulseConfig.getProfile() + "/" + currentDir;
        Path path = Paths.get(absPath);

        Files.copy(path, response.getOutputStream());
    }

    /**
     * 导入sor文件
     *
     * @param file
     * @param updateSupport
     * @param operName
     * @return
     */
    @Override
    public String importSor(MultipartFile file, boolean updateSupport, String operName) {
        Map<String, Object> res = Sor.parse(file);
        if(!res.get("status").equals("ok")){
            throw new ServiceException("sor文件解析失败");
        }

        try {
            SorInfo sorInfo = (SorInfo) res.get("sorInfo");
            FxdParamsVo FxdParams = sorInfo.getFxdParams();
            // 事件
            KeyEventsVo keyEvents = sorInfo.getKeyEvents();

            // IOR 折射率
            Double ior = Double.parseDouble(FxdParams.getIndex());


            // PKP 点间距
            double pkp = (double) FxdParams.getResolution() * 1000.0;

            // PW 脉宽
            long pw = (long) (Double.parseDouble(FxdParams.getPulseWidth().split(" ")[0]));

            // RD 量程
            long rd = (long) (Double.parseDouble(FxdParams.getAcquisitionRangeDistance()));

            // backScatter  回散系数
            Double backScatter = Double.parseDouble(FxdParams.getBc().split(" ")[0]);

            // finalThreshold 结束门限
            Double finalThreshold = Double.parseDouble(FxdParams.getEotThr().split(" ")[0]);

            // nonReflectThreshold 非反射门限
            Double nonReflectThreshold = Double.parseDouble(FxdParams.getLossThr().split(" ")[0]);

            // reflectThreshold 反射门限
            Double reflectThreshold =  Double.parseDouble(FxdParams.getReflThr().split(" ")[0]);

            // testTime 测试时间
            long testTime = (long) (Double.parseDouble(FxdParams.getAveragingTime().split(" ")[0]));

            // waveLength 波长
            long waveLength = (long) (Double.parseDouble(FxdParams.getWavelength().split(" ")[0]));

            // 总回波损耗
            Double orl = keyEvents.getSummary().getOrl();

            // wholeAtten 全程衰耗
            Double wholeAtten = keyEvents.getSummary().getTotalLoss();

            // wholeLen 全程长度
            Double wholeLen = keyEvents.getSummary().getLossEnd();

            // wholeAvgAtten 全程均耗
            Double wholeAvgAtten = wholeAtten / wholeLen;



            List<CircuitMeasureEvent> events = new ArrayList<>();
            Double startPrev = 0d;
            for (EventVo event : keyEvents.getEvents()) {
                CircuitMeasureEvent e = new CircuitMeasureEvent();
                // index
                e.setIndex(event.getEventNum());

                // type
                String type = event.getType();
                if (type.startsWith("1F")) {
                    if (event.getEventNum() == 1) {
                        e.setType(1);
                    } else {
                        e.setType(3);
                    }
                } else if (type.startsWith("1E")) {
                    e.setType(2);
                } else if (type.startsWith("0F")) {
                    e.setType(4);
                } else if (type.startsWith("2F")) {
                    e.setType(5);
                }

                // startDist 距离 float
                Double startDist = Double.parseDouble(event.getDistance());
                e.setStartDist(startDist.toString());

                // startLocation 该事件的起始序号 = 距离/点间距
                long startLocation = (long) (startDist / pkp);
                e.setStartLocation(startLocation);

                // 斜率（分段均耗）
                Double slope = Double.parseDouble(event.getSlope());
                e.setSegAvgAtten(slope.toString());

                // 当前事件起始位置
                Double startCurr = Double.parseDouble(event.getStartOfCurr());
                // 分段长度 = 当前事件起始位置-上一事件起始位置
                Double segLen = startCurr - startPrev;
                e.setSegLen(segLen.toString());  // 分段长度 = 当前事件起始位置-上一事件起始位置

                // 分段衰耗 = 斜率 * 分段长度
                Double segAtten = slope * segLen;
                e.setSegAtten(segAtten.toString());  // 分段衰耗 = 斜率 * 分段长度

                // insertLoss 插入损耗
                e.setInsertLoss(event.getSpliceLoss());

                // returnLoss 回波损耗
                e.setReturnLoss(event.getReflLoss());

                events.add(e);

                startPrev = startCurr;
            }

            String fileUrl = null;

            // 上传文件
            try {
                fileUrl = FileUploadUtils.upload(file);
            } catch (Exception e) {
                throw new ServiceException("文件上传失败");
            }

            if (fileUrl == null) {
                throw new ServiceException("文件上传失败");
            }

            FilePath filePath = new FilePath();
            filePath.setFilePath(fileUrl);
            filePath.setFileName(file.getOriginalFilename());
            filePathService.insertFilePath(filePath);

            // 插入数据库
            CircuitMeasure circuitMeasure = new CircuitMeasure();
            circuitMeasure.setFileId(filePath.getFileId());
            circuitMeasure.setParamWaveLength(waveLength);
            circuitMeasure.setParamPw(pw);
            circuitMeasure.setParamIor(ior.toString());
            circuitMeasure.setParamBackScatter(Math.abs(backScatter)+"");
            circuitMeasure.setParamTestTime(testTime);
            circuitMeasure.setParamRd(rd);
            circuitMeasure.setParamNonReflectThreshold(nonReflectThreshold.toString());
            circuitMeasure.setParamReflectThreshold(Math.abs(reflectThreshold)+"");
            circuitMeasure.setParamFinalThreshold(finalThreshold.toString());

            String dateString = FxdParams.getDateTime();
            // 定义日期格式
            SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
            try {
                // 解析字符串为 Date 对象
                Date date = format.parse(dateString.split("\\(")[0].trim());
                circuitMeasure.setCreateTime(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }


            // 测试模式
            circuitMeasure.setParamTestMode(0L);

            circuitMeasure.setDefaultMeasure(0);
            circuitMeasure.setType(4);
            circuitMeasure.setStatus(0);
            circuitMeasure.setCircuitStatus(0);

            circuitMeasure.setTotalReturnLoss(orl.toString());
            circuitMeasure.setWholeAtten(wholeAtten.toString());
            circuitMeasure.setWholeLen(wholeLen.toString());
            circuitMeasure.setWholeAvgAtten(wholeAvgAtten.toString());

            circuitMeasure.setCreateBy(operName);
            circuitMeasureMapper.insertCircuitMeasure(circuitMeasure);

            for (CircuitMeasureEvent event : events) {
                event.setMeasureId(circuitMeasure.getMeasureId());
                circuitMeasureEventService.insertCircuitMeasureEvent(event);
            }

        } catch (Exception e) {
            throw new ServiceException("导入失败");
        }
        return "导入成功！";
    }
}
